home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d7 / laser4up.arc / LASER4UP.ASM next >
Assembly Source File  |  1989-03-28  |  41KB  |  1,061 lines

  1.         PAGE    75,132
  2.         TITLE   "LASERLST - List file to HP LaserJet"
  3. ;
  4. ; The original LASERLST program by Michael Holmes and Bob Flanders formats
  5. ; and prints two 80-column pages side-by-side on one 8.5x11 inch page on
  6. ; a HP LaserJet printer.  The program thus allows you to cut your paper
  7. ; usage in half.
  8. ;
  9. ; The LASER4UP program is the LASERLST program modified to send what would
  10. ; be every other *physical* page to a disk file with all the appropriate 
  11. ; LaserJet control codes. This allows you to print on the front side of
  12. ; each page, then put the pages back into the original order, flip them
  13. ; over in the printer, and then print every other physical page on the
  14. ; back.  This cuts your paper usage to one-fourth of what it would have 
  15. ; been without LASERLST or LASER4UP.  LASERLST would work fine without
  16. ; modification if everyone was using the LaserJet IID, which has the
  17. ; capability of printing on the back side of the page automatically.
  18. ; Unfortunately, this is not so... LASER4UP requires re-sorting the 
  19. ; printed output and re-inserting that back into the printer, so it's a bit
  20. ; more trouble to use than LASERLST, but it does have the advantage of 
  21. ; minimizing the paper required to print your documentation or program 
  22. ; listings.
  23. ;
  24. ; Original LASERLST program by Michael Holmes and Bob Flanders
  25. ; Modified LASER4UP program by Bob White 3/28/89.
  26. ;
  27. CSEG        SEGMENT PARA PUBLIC 'CODE'
  28.         ASSUME  CS:CSEG, DS:CSEG, ES:CSEG, SS:CSEG
  29.         ORG     100H
  30.  
  31. START:        JMP     MAIN            ; go to start of program
  32.  
  33. HEADER_MSG  DB        "LaserLst 1.1 (c) 1989 Ziff Communications Co.", 0DH,0AH
  34.         DB        "PC Magazine",254," Michael Holmes & Bob Flanders",0DH,0AH
  35. CRLF        DB        0DH,0AH
  36. DOLLAR        DB        "$"
  37. ; ---------------------------------------------------------------------------
  38. ;   Initialized work areas
  39. ; ---------------------------------------------------------------------------
  40. ARG1        DW        0                ; addr of first argument
  41. ARG2        DW        0                ; addr of second argument
  42. CHandle     DW      0                       ;; Current output handle
  43. NHandle     DW      0                       ;; Next output handle
  44. BHandle     DW      0                       ;; Back side file handle
  45. PHANDLE     DW        4                ; printer handle (stdprn)
  46. TABCOL        DW        8                ; tab width
  47. NEWPAGE     DB        0                ; new page requested flag
  48. HPSTATE     DB        0                ; printer state  (1 = initialized)
  49. BackFile    DB      "LASER4UP.TXT",0        ;; ASCIIZ back side file name
  50.  
  51. TITLE_        DB        1BH,"&dD"               ; title line for heading
  52. TITLE_DTE   DB        "mm/dd/yyyy  "          ; ..and display
  53. TITLE_TME   DB        "hh:mm       Filename: "
  54. TITLE_FLE   DB        19 dup(32)
  55. TITLE_DSP   EQU     $-TITLE_DTE
  56.         DB        "                    Page"
  57. TITLE_PGE   DB        "xxxx",0dh,0ah,0ah
  58.         DB        1BH,"&d@"
  59. TITLE_LEN   EQU     $-TITLE_            ; length of title
  60. ;----------------------------------------------------------------------
  61. ;   DTA structure for DOS "find matching" call
  62. ;----------------------------------------------------------------------
  63. DTA        EQU     80H             ; dta offset
  64. DTA_ATTR    EQU     BYTE PTR DTA+21        ; file attribute
  65. DTA_TIME    EQU     WORD PTR DTA_ATTR+1     ; file time
  66. DTA_DATE    EQU     WORD PTR DTA_TIME+2     ; file date
  67. DTA_LSIZ    EQU     WORD PTR DTA_DATE+2     ; file lsw of size
  68. DTA_HSIZ    EQU     WORD PTR DTA_LSIZ+2     ; file msw of size
  69. DTA_NAME    EQU     BYTE PTR DTA_HSIZ+2     ; file name of file
  70. DTA_LEN     EQU     DTA_NAME+15-DTA        ; length of dta find entry
  71. ;----------------------------------------------------------------------
  72. ;   Messages to user
  73. ;----------------------------------------------------------------------
  74. FILENF        DB        "File not found.",0DH,0AH,"$"
  75. PRTOERR     DB        "Could not open output file.",0DH,0AH,"$"
  76. Backerr     DB      "Could not open back side output file.",0Dh,0Ah,"$"
  77. FORMAT        DB        0DH,0AH,"SYNTAX:",09H,"LASERLST [d:][path]filename[.ext] "
  78.         DB        "[outfile] [/Tn]",0DH, 0AH, 0AH
  79.         DB        "  ofile defaults to LPT1:",0DH,0AH
  80.         DB        "  n is tab width (16 max)",0DH,0AH,"$"
  81. ;----------------------------------------------------------------------
  82. ;   HP control strings
  83. ;----------------------------------------------------------------------
  84. STRING1     DB        1BH,"E",1BH,"&l1O",1BH,"(s17H",1BH,"&l5.14C"
  85.         DB        1BH,"&l71F",1BH,"&l6E",1BH,"(s-3B"
  86.         DB        1BH,"&a0R",1BH,"&a85M",1BH,"&a5L",0DH
  87. STRING1_LEN EQU     $-STRING1
  88.  
  89. STRING2     DB        0ch,1BH,"E"
  90. STRING2_LEN EQU     $-STRING2
  91.  
  92. STRING3     DB        1BH,"&a0R",1BH,"&a90M",1BH,"&a88L",0DH,0AH,0DH,0AH
  93. STRING3_LEN EQU     $-STRING3
  94.  
  95. STRING4     DB        "|", 0DH,0AH
  96.  
  97. STRING5     DB        1BH,"&a0R",1BH,"&a171M",1BH,"&a91L",0DH
  98. STRING5_LEN EQU     $-STRING5
  99.  
  100. ;
  101. ; Note: leading formfeed (0Ch) replaced by carriage return (0Dh) for
  102. ; the first pass through each input file.  Changed to FF in code.
  103. ;
  104. STRING6     DB        0Dh,1BH,"&a0R",1BH,"&a85M",1BH,"&a5L",0DH
  105. STRING6_LEN EQU     $-STRING6
  106. ; ---------------------------------------------------------------------------
  107. ;   MAIN - Mainline of program
  108. ; ---------------------------------------------------------------------------
  109. MAIN        PROC                ; start of program
  110.  
  111.         CALL    INIT            ; initialize program
  112.  
  113. MAIN10:     CALL    OPEN            ; open the input file
  114.         JC        MAIN80            ; if we can't .. try next
  115.  
  116. MAIN20:     CALL    READ            ; read a block
  117.  
  118.         CALL    PRINT            ; print the line
  119.  
  120.         OR        SI, SI            ; q. end of file?
  121.         JNZ     MAIN20            ; a. no .. get next line
  122.  
  123.         MOV     BX, FHANDLE         ; bx = input file handle
  124.         MOV     AH, 3EH            ; ah = close file
  125.         INT     21H             ; .. ask DOS to do it
  126.  
  127. MAIN80:     MOV     AH, 4FH            ; ah = find next file
  128.         INT     21H             ; q. file found?
  129.         JNC     MAIN10            ; a. yes .. continue
  130.  
  131.             Mov     BX,BHandle              ;; Get back side file handle
  132.             Mov     AH,3Eh                  ;; AH = close file
  133.             Int     21h                     ;; Ask DOS to do it.
  134.  
  135.         MOV     DX, OFFSET DOLLAR        ; dx -> null message
  136.         CALL    DIE             ; .. say goodnight
  137.  
  138. MAIN        ENDP
  139. ; ---------------------------------------------------------------------------
  140. ;   INIT - Handle initialization
  141. ; ---------------------------------------------------------------------------
  142. INIT        PROC
  143.  
  144.         CLD                 ; assure ascending
  145.         MOV     AH, 19H            ; ah = get current drive
  146.         INT     21H             ; al = current drive
  147.         MOV     EDRV, AL            ; save entry drive
  148.  
  149.         MOV     SI, OFFSET EDIR        ; si -> current directory area
  150.         MOV     BYTE PTR [SI], '\'      ; .. start with backslash
  151.         INC     SI                ; si -> next byte
  152.         XOR     DL, DL            ; dl = default drive
  153.         MOV     AH, 47H            ; ah = get current dir
  154.         INT     21H             ; .. save in area
  155.  
  156.             Mov     DX,Offset BackFile      ;; Point to filename to create
  157.             Mov     AH,3Ch                  ;; DOS Create file call
  158.             Xor     CX,CX                   ;; File attributes (none)
  159.             Int     21h                     ;; Call DOS to do it.
  160.             Jnc     Init05                  ;; Continue if no error on create
  161.  
  162.             Mov     DX,Offset Backerr       ;; Point to error message
  163.             Call    Die                     ;; And bail out...
  164.  
  165. Init05:     Mov     BHandle,AX              ;; Save file handle
  166.  
  167.         MOV     DX, OFFSET HEADER_MSG   ; dx -> header message
  168.         MOV     AH, 9            ; ah = print ascii$ message
  169.         INT     21H             ; .. ask DOS to do it
  170.  
  171.         CALL    PARMS            ; check parameters
  172.  
  173.         CMP     ARG2, 0            ; q. arg2 specified?
  174.         JE        INIT20            ; a. yes .. skip open
  175.  
  176.         MOV     DX, ARG2            ; dx -> arg2 value
  177.         MOV     AH, 3CH            ; ah = create file
  178.         XOR     CX, CX            ; .. cx = file attributes
  179.         INT     21H             ; q. open the file ok?
  180.         JNC     INIT10            ; a. yes .. continue
  181.  
  182.         MOV     DX, OFFSET PRTOERR        ; dx -> open error message
  183.         CALL    DIE             ; .. you're dead, Jim.
  184.  
  185. INIT10:     MOV     PHANDLE, AX         ; save printer handle
  186.  
  187. INIT20:     CALL    DFLPATH            ; set up dir & drive
  188.  
  189.         MOV     AH, 4EH            ; ah = find first
  190.         MOV     DX, OFFSET FILENAME     ; dx -> file to find
  191.         XOR     CX, CX            ; cx = search attribute
  192.         INT     21H             ; q. find first file ok?
  193.         JNC     INIT90            ; a. yes .. continue
  194.  
  195.         MOV     DX, OFFSET FILENF        ; dx -> file not found
  196.         CALL    DIE             ; .. gasp you're final breath
  197.  
  198. INIT90:     RET                 ; return to caller
  199.  
  200. INIT        ENDP
  201. ; ---------------------------------------------------------------------------
  202. ;   OPEN - Opens the next file to process and update title line
  203. ;     Exit: Carry indicates file would not open.
  204. ; ---------------------------------------------------------------------------
  205. OPEN        PROC
  206.  
  207.         MOV     DX, OFFSET DTA_NAME     ; dx -> file name
  208.         MOV     AX, 3D00H            ; al = open for read
  209.         INT     21H             ; .. ask DOS to do it.
  210.         JNC     OPEN05            ; ok .. continue
  211.  
  212.         RET                 ; else .. return if error
  213.  
  214. OPEN05:     MOV     FHANDLE, AX         ; save file handle
  215.         MOV     LASTBUFF, 0         ; show last buffer not read
  216.  
  217.         MOV     SI, OFFSET DTA_NAME     ; si -> file name
  218.         MOV     DI, OFFSET TITLE_FLE    ; di -> file name area
  219.         PUSH    DI                ; .. save it
  220.         MOV     AL, ' '                 ; al = blank
  221.         MOV     CX, 15            ; .. amount to blank
  222.       REP   STOSB                ; .. clear the file name
  223.         POP     DI                ; .. restore output pointer
  224.  
  225. OPEN10:     LODSB                ; al = byte from file name
  226.  
  227.         OR        AL, AL            ; q. end of name?
  228.         JZ        OPEN20            ; a. yes .. end loop
  229.  
  230.         STOSB                ; store a byte
  231.         JMP     OPEN10            ; .. and move next
  232.  
  233. OPEN20:     MOV     BL, '0'                 ; fill value
  234.         MOV     AX, DS:DTA_DATE        ; ax = date field
  235.         PUSH    AX                ; save for later
  236.         PUSH    AX                ; .. again
  237.  
  238.         MOV     CL, 5            ; cl = shift value
  239.         SHR     AX, CL            ; .. mm to lower bits
  240.         AND     AX, 0FH            ; .. upper bits off
  241.         MOV     CX, 2            ; cx = number of characters
  242.         MOV     DI, OFFSET TITLE_DTE    ; di -> mm
  243.         CALL    ITOA            ; .. move in mm
  244.  
  245.         POP     AX                ; ax = date
  246.         AND     AX, 1FH            ; al = dd
  247.         MOV     CX, 2            ; cx = number of chars
  248.         MOV     DI, OFFSET TITLE_DTE+3  ; di -> dd
  249.         CALL    ITOA            ; .. move into dd
  250.  
  251.         POP     AX                ; ax = date
  252.         MOV     CL, 9            ; cl = shift amount
  253.         SHR     AX, CL            ; .. ax = yy
  254.         ADD     AX, 1980            ; ax = year
  255.         MOV     CX, 4            ; cx = length of output
  256.         MOV     DI, OFFSET TITLE_DTE+6  ; di -> yyyy
  257.         CALL    ITOA            ; .. move into yyyy
  258.  
  259.         MOV     AX, DS:DTA_TIME        ; ax = time
  260.         PUSH    AX                ; .. save for later
  261.         MOV     CL, 11            ; cl = shift value
  262.         SHR     AX, CL            ; .. ax = hh
  263.         MOV     CX, 2            ; cx = length of output
  264.         MOV     DI, OFFSET TITLE_TME    ; di -> hh
  265.         CALL    ITOA            ; .. move into hh
  266.  
  267.         POP     AX                ; ax = time
  268.         MOV     CL, 5            ; cl = shift value
  269.         SHR     AX, CL            ; ax = mm
  270.         AND     AX, 3FH            ; .. upper bits off
  271.         MOV     CX, 2            ; cx = length of output
  272.         MOV     DI, OFFSET TITLE_TME+3  ; di -> mm
  273.         CALL    ITOA            ; .. move into mm
  274.  
  275.         MOV     AH, 40H            ; ah = write to device
  276.         MOV     BX, 1            ; bx = stdout device
  277.         MOV     CX, TITLE_DSP        ; cx = length to display
  278.         MOV     DX, OFFSET TITLE_DTE    ; dx -> part of header line
  279.         INT     21H             ; issue dos call
  280.  
  281.         MOV     AH, 40H            ; ah = write to device
  282.         MOV     BX, 1            ; bx = stdout device
  283.         MOV     CX, 2            ; cx = length to display
  284.         MOV     DX, OFFSET CRLF        ; dx -> <cr><lf> string
  285.         INT     21H             ; issue dos call
  286.  
  287.         CLC                 ; show all went ok
  288. OPEN90:     RET
  289.  
  290. OPEN        ENDP
  291. ; ---------------------------------------------------------------------------
  292. ;   READ - Read the next buffer full
  293. ;     Exit: si -> next line, 0 if eof, cx =  length of line
  294. ; ---------------------------------------------------------------------------
  295. READ        PROC
  296.  
  297.         PUSH    AX                ; save registers
  298.         PUSH    BX
  299.         PUSH    DX
  300.  
  301.         MOV     SI, 0            ; si -> nothing
  302.  
  303.         CMP     LASTBUFF, 1         ; q. last buffer have 1ah?
  304.         JE        READ90            ; a. yes .. end it all
  305.  
  306.         MOV     AH, 03FH            ; ah = read file
  307.         MOV     BX, FHANDLE         ; bx = handle of file to read
  308.         MOV     CX, BUFLEN            ; cx = amount to read
  309.         MOV     DX, OFFSET BUFFER        ; dx -> buffer
  310.         INT     21H             ; read, please
  311.         JC        READ90            ; error .. return eof
  312.  
  313.         OR        AX, AX            ; q. any read?
  314.         JZ        READ90            ; a. yes .. return with something
  315.  
  316.         MOV     SI, OFFSET BUFFER        ; si -> start of line
  317.         MOV     CX, AX            ; cx = nbr of characters read
  318.         MOV     BX, AX            ; .. and bx
  319.  
  320.         MOV     DI, SI            ; di -> chars read
  321.         MOV     AL, 1AH            ; al = EOF indicator
  322.  
  323.     REPNE   SCASB                ; q. eof found?
  324.         JNE     READ80            ; a. no .. continue
  325.  
  326.         INC     CX                ; .. increment count
  327.         NEG     CX                ; .. and negate it
  328.         MOV     LASTBUFF, 1         ; .. and set lastbuff flag
  329.  
  330. READ80:     ADD     CX, BX            ; q. any bytes this buffer?
  331.         JNZ     READ90            ; a. yes .. continue
  332.  
  333.         MOV     SI, 0            ; a. else .. show end of file.
  334.  
  335. READ90:     POP     DX                ; restore registers
  336.         POP     BX                ;
  337.         POP     AX                ;
  338.         RET                 ; ..and return to caller
  339.  
  340. READ        ENDP
  341. ; ---------------------------------------------------------------------------
  342. ;   PRINT - Print requested data
  343. ;     Entry: si -> string to print or 0, cx =  length of input string
  344. ; ---------------------------------------------------------------------------
  345. PRINT        PROC
  346.  
  347.         OR        SI, SI            ; q. end of file call?
  348.         JNE     PRINT10            ; a. no .. continue
  349.  
  350.         CALL    EPILOGUE            ; put out trailing characters
  351.         RET                 ; ..and return to caller
  352.  
  353. PRINT10:    PUSH    AX                ; save registers
  354.         PUSH    BX
  355.         PUSH    CX
  356.         PUSH    DX
  357.         PUSH    SI
  358.  
  359.         CMP     HPSTATE, 0            ; q. initial state?
  360.         JNE     PRINT20            ; a. no .. continue
  361.  
  362.         CALL    PROLOGUE            ; send out initial string
  363.  
  364. PRINT20:    CALL    EXPAND            ; handle tab expansion
  365.         MOV     DX, SI            ; dx -> start of new buffer
  366.         MOV     BX, CX            ; bx = nbr of chars in buffer
  367.         XOR     CX, CX            ; cx = nbr of chars to print
  368.         MOV     AH, USEDLEN         ; ah = printed chars in this line
  369.  
  370. PRINT30:    LODSB                ; al = first character
  371.  
  372.         CMP     AL, 0CH            ; q. formfeed?
  373.         JNE     PRINT40            ; a. yes .. process it
  374.  
  375.         CALL    LINEPRT            ; print the line
  376.         CALL    PAGEBREAK            ; do a page break
  377.         XOR     AH, AH            ; ah = nbr of columns used
  378.         DEC     BX                ; bx = decrement remaining count
  379.         INC     DX                ; dx -> next printable character
  380.         JMP     PRINT70            ; ..and continue w/common code
  381.  
  382. PRINT40:    CMP     AL, 0AH            ; q. linefeed?
  383.         JNE     PRINT50            ; a. no .. continue
  384.  
  385.         DEC     BX                ; bx = remaining chars in buffer
  386.         INC     CX                ; cx = nbr of characters to print
  387.         CALL    LINEPRT            ; print the line
  388.         XOR     AH, AH            ; ah = nbr of columns used
  389.         CALL    BUMPLINE            ; increment/test line counter
  390.         JMP     PRINT70            ; ..and continue w/common code
  391.  
  392. PRINT50:    CMP     AL, 0DH            ; q. carriage return?
  393.         JNE     PRINT55            ; a. no .. continue
  394.         JMP     SHORT PRINT57        ; ..and continue w/common code
  395.  
  396. PRINT55:    CMP     AL, 08H            ; q. BackSpace?
  397.         JNE     PRINT60            ; a. no .. continue
  398.  
  399.         DEC     AH                ; move back a column
  400.         JNS     PRINT65            ; .. but not beyond first
  401.  
  402. PRINT57:    XOR     AH, AH            ; ah = start of line
  403.         JMP     SHORT PRINT65        ; .. and continue
  404.  
  405. PRINT60:    INC     AH                ; increment nbr of columns used
  406. PRINT65:    INC     CX                ; ..and nbr of chars to print
  407.         DEC     BX                ; decrement remaining char count
  408.  
  409.         CMP     AH, 81            ; q. reached end of line?
  410.         JL        PRINT70            ; a. no .. continue
  411.  
  412.         CALL    LINEPRT            ; print upto page width
  413.         PUSH    CX                ; save registers
  414.         PUSH    DX                ;
  415.         MOV     DX, OFFSET CRLF        ; dx -> <cr><lf>
  416.         MOV     CX, 2            ; cx = string length
  417.         CALL    WRITE            ; print the crlf to do line wrapping
  418.         POP     DX                ; restore registers
  419.         POP     CX                ;
  420.         XOR     AH, AH            ; ah = nbr of columns used
  421.         CALL    BUMPLINE            ; increment/test line counter
  422.  
  423. PRINT70:    OR        BX, BX            ; q. anything left to check?
  424.         JNZ     PRINT30            ; a. yes .. loop till done
  425.  
  426.         CALL    LINEPRT            ; print the line
  427.         MOV     USEDLEN, AH         ; save nbr of columns used
  428.  
  429.         POP     SI                ; restore registers
  430.         POP     DX                ;
  431.         POP     CX                ;
  432.         POP     BX                ;
  433.         POP     AX                ;
  434.         RET                 ; ..and return to caller
  435.  
  436. PRINT        ENDP
  437. ; ---------------------------------------------------------------------------
  438. ;   DIE - Display an error message and return to DOS
  439. ;     Entry: dx -> error message ended in dollar sign.
  440. ; ---------------------------------------------------------------------------
  441. DIE        PROC
  442.  
  443.         MOV     AH, 9            ; ah = print string
  444.         INT     21H             ; .. call dos to print error
  445.  
  446.         MOV     DL, EDRV            ; dl = drive to select
  447.         MOV     AH, 0EH            ; ah = select drive
  448.         INT     21H             ; .. select the drive
  449.  
  450.         MOV     DX, OFFSET EDIR        ; dx -> directory
  451.         MOV     AH, 3BH            ; ah = CHDIR request
  452.         INT     21H             ; .. ask DOS to do it
  453.  
  454.         MOV     AX, 4C00H            ; ax = exit
  455.         INT     21H             ; .. terminate routine
  456.  
  457. DIE        ENDP
  458. ; ---------------------------------------------------------------------------
  459. ;   PARMS - Parses the command line
  460. ; ---------------------------------------------------------------------------
  461. PARMS        PROC
  462.  
  463.         CALL    UPCASE            ; upper case the parm area
  464.         MOV     SI, 81H            ; si -> parms area
  465.  
  466. PARMS10:    LODSB                ; get parameter character
  467.  
  468.         CMP     AL, '/'                 ; q. option?
  469.         JE        PARMS80            ; a. yes .. check option
  470.         CMP     AL, 0DH            ; q. end of line?
  471.         JE        PARMS50            ; a. yes .. exit
  472.         CMP     AL, ' '                 ; q. blank?
  473.         JNA     PARMS10            ; a. yes .. skip
  474.         CALL    ARG             ; set the argument
  475.         JC        PARMSERR            ; .. die on an error
  476.  
  477. PARMS30:    LODSB                ; get next character
  478.         CMP     AL, 0DH            ; q. end of line?
  479.         JE        PARMS50            ; a. yes .. process
  480.         CMP     AL, '/'                 ; q. start of option?
  481.         JE        PARMS80            ; a. yes .. process
  482.         CMP     AL, ' '                 ; q. end of PARMS?
  483.         JA        PARMS30            ; a. no .. next char
  484.  
  485.         CALL    ENDPARM            ; terminate parm string
  486.         JMP     PARMS10            ; .. look for next
  487.  
  488. PARMS50:    CALL    ENDPARM            ; terminate parm string
  489.  
  490.         CMP     ARG1, 0            ; q. PARMS 1 available?
  491.         JE        PARMSERR            ; a. no .. error
  492.         RET                 ; .. else .. return to caller
  493.  
  494. PARMS80:    CALL    ENDPARM            ; terminate parm string
  495.         LODSB                ; al = option character
  496.  
  497.         CMP     AL, 'T'                 ; q. Tab width?
  498.         JNE     PARMSERR            ; a. no .. error in option
  499.  
  500.         CALL    ATOI            ; ax =  tab width
  501.  
  502.         CMP     AX, 16            ; q. request greater than max?
  503.         JG        PARMS10            ; a. yes .. unreasonable
  504.  
  505.         MOV     TABCOL, AX            ; .. save tab width
  506.         JMP     PARMS10            ; .. continue scan
  507.  
  508. PARMSERR:   MOV     DX, OFFSET FORMAT        ; dx -> format message
  509.         CALL    DIE             ; abort
  510.  
  511. PARMS        ENDP
  512. ; ---------------------------------------------------------------------------
  513. ;   ARG - Setup pointers to the command line arguments
  514. ;     Entry: si -> second character in argument.
  515. ;     Exit: ARG1 or ARG2 pointers filled in.
  516. ;    Carry set if more than 2 arguments detected.
  517. ; ---------------------------------------------------------------------------
  518. ARG        PROC
  519.  
  520.         LEA     BX, [SI-1]            ; bx -> argument
  521.         CMP     ARG1, 0            ; q. arg1 filled in?
  522.         JNE     ARG10            ; a. yes .. check 2
  523.         MOV     ARG1, BX            ; save arg1 pointer
  524.         JMP     SHORT ARG90         ; .. exit ok!
  525.  
  526. ARG10:        CMP     ARG2, 0            ; q. arg2 filled in?
  527.         JE        ARG20            ; a. no .. fill it in
  528.         STC                 ; else .. error
  529.         RET                 ; .. and return to caller
  530.  
  531. ARG20:        MOV     ARG2, BX            ; save arg2 pointer
  532. ARG90:        CLC                 ; show no error
  533.         RET                 ; return to caller
  534.  
  535. ARG        ENDP
  536. ; ---------------------------------------------------------------------------
  537. ;   ENDPARM - Handle parameters which end in a colon
  538. ;     Entry: si -> first character past end of parameter
  539. ; ---------------------------------------------------------------------------
  540. ENDPARM     PROC
  541.  
  542.         CMP     BYTE PTR [SI-2], ':'    ; q. argument end in a colon?
  543.         JNE     ENDPARM10            ; a. no .. continue
  544.  
  545.         MOV     BYTE PTR [SI-2], 0        ; ..it doesn't any more
  546.         RET                 ; ..and return
  547.  
  548. ENDPARM10:  MOV     BYTE PTR [SI-1], 0        ; end the parameter
  549.         RET                 ; ..and return
  550.  
  551. ENDPARM     ENDP
  552. ; ---------------------------------------------------------------------------
  553. ;   DFLPATH - Setup the default drive and path
  554. ; ---------------------------------------------------------------------------
  555. DFLPATH     PROC
  556.  
  557.         MOV     DI, ARG1            ; di -> first arg
  558.  
  559. DFLPATH10:  CMP     BYTE PTR [DI+1], ':'    ; q. drive specified?
  560.         JNE     DFLPATH20            ; a. no .. use current drive
  561.         MOV     DL, [DI]            ; dl = drive to use
  562.         SUB     DL, 'A'                 ; get requested drive number
  563.         MOV     AH, 0EH            ; set requested drive
  564.         INT     21H             ; .. via dos
  565.         ADD     DI, 2            ; di -> next part
  566.  
  567. DFLPATH20:  PUSH    DI                ; save pointer
  568.         MOV     BX, DI            ; bx -> start of area
  569.         XOR     AL, AL            ; al = search for null
  570.         MOV     CX, 128            ; very max to search
  571.         CLD
  572.     REPNE   SCASB                ; find end of arg
  573.         LEA     SI, [DI-1]            ; si -> nul
  574.         MOV     CX, 0            ; cx = # chars to move
  575.         CMP     SI, BX            ; q. any file name
  576.         JE        DFLPATH80            ; a. no .. error
  577.  
  578. DFLPATH30:  DEC     SI                ; si -> prev char
  579.         CMP     BYTE PTR [SI], '\'      ; q. dir?
  580.         JE        DFLPATH35            ; a. yes .. end of file name.
  581.         INC     CX                ; cx = char count
  582.         CMP     SI, BX            ; q. done?
  583.         JE        DFLPATH37            ; a. yes .. move file name
  584.         JMP     DFLPATH30            ; .. continue
  585.  
  586. DFLPATH35:  INC     SI                ; si -> start of file name
  587. DFLPATH37:  OR        CX, CX            ; q. file name spec'd?
  588.         JZ        DFLPATH80            ; a. no .. error
  589.         CMP     CX, 12            ; q. too long?
  590.         JA        DFLPATH85            ; a. yes .. error
  591.         PUSH    SI                ; save start pointer
  592.         MOV     DI, OFFSET FILENAME     ; di -> file name
  593.         INC     CX                ; .. assure nul moves too
  594.      REP    MOVSB                ; .. move in the file name
  595.         POP     SI                ; restore start pointer
  596.         POP     DI                ; .. and dir pointer
  597.         CMP     SI, BX            ; q. at start of parm?
  598.         JE        DFLPATH90            ; a. yes .. return
  599.         INC     BX                ; bx -> next char
  600.         CMP     SI, BX            ; q. root only given?
  601.         JE        DFLPATH40            ; a. yes .. continue
  602.         DEC     SI                ; si -> last \
  603.  
  604. DFLPATH40:  MOV     BYTE PTR [SI], 0        ; make dir ASCIIZ
  605. DFLPATH50:  MOV     DX, DI            ; dx -> directory
  606.         MOV     AH, 3BH            ; ah = CHDIR opcode
  607.         INT     21H             ; .. change directory
  608.         JNC     DFLPATH90            ; if ok .. continue
  609.         JMP     SHORT DFLPATH85        ; dx -> baddir request
  610.  
  611. DFLPATH80:  MOV     DX, OFFSET FORMAT        ; dx -> no file specified
  612.         CALL    DIE
  613.  
  614. DFLPATH85:  MOV     DX, OFFSET FILENF        ; dx -> invalid filename spec'd
  615.         CALL    DIE
  616.  
  617. DFLPATH90:  RET                 ; return to caller
  618.  
  619. DFLPATH     ENDP
  620. ; ---------------------------------------------------------------------------
  621. ;   EXPAND - Handle tab expansion
  622. ;     Entry:
  623. ;    si -> line read from file ended by a linefeed
  624. ;    cx =  length of line
  625. ;     Exit:
  626. ;    si -> reformatted line in output buffer
  627. ;    cx =  new line length
  628. ; ---------------------------------------------------------------------------
  629. EXPAND        PROC
  630.  
  631.         PUSH    AX                ; save registers
  632.         PUSH    BX
  633.         PUSH    DX
  634.         PUSH    DI
  635.  
  636.         MOV     DI, OFFSET OBUFF        ; di -> start of output buffer
  637.  
  638. EXPAND10:   LODSB                ; al = character from input line
  639.  
  640.         CMP     AL, 09H            ; q. tab character?
  641.         JNE     EXPAND30            ; a. no .. continue processing
  642.  
  643.         MOV     AX, CURCOL            ; ax = current column
  644.         DEC     AX                ; ax = column offset
  645.         XOR     DX, DX            ; dx:ax = current column
  646.         MOV     BX, TABCOL            ; bx = nbr of columns per tab
  647.         IDIV    BX                ; dx = space within tab stop
  648.  
  649.         SUB     BX, DX            ; bx = spaces left in tab stop
  650.  
  651.         MOV     AL, 20H            ; al = space char to padding string
  652.  
  653. EXPAND20:   STOSB                ; put a blank in output buffer
  654.         INC     CURCOL            ; bump current column nbr
  655.  
  656.         DEC     BX                ; q. done yet?
  657.         JNZ     EXPAND20            ; a. no .. keep looping
  658.         JMP     SHORT EXPAND50        ; a. yes .. get next character
  659.  
  660. EXPAND30:   CMP     AL, 0DH            ; q. carriage return?
  661.         JE        EXPAND33            ; a. yes .. reset column
  662.  
  663.         CMP     AL, 0CH            ; q. form feed?
  664.         JNE     EXPAND35            ; a. no .. continue processing
  665.  
  666. EXPAND33:   MOV     CURCOL, 0            ; setup for start of new line
  667.         JMP     SHORT EXPAND40        ; .. continue
  668.  
  669. EXPAND35:   CMP     AL, 08H            ; q. backspace?
  670.         JNE     EXPAND40            ; a. no .. continue
  671.  
  672.         STOSB                ; save the BS
  673.         DEC     CURCOL            ; .. move back a space
  674.         JNZ     EXPAND50            ; .. get next character
  675.  
  676.         MOV     CURCOL, 1            ; init current column
  677.         JMP     SHORT EXPAND50        ; .. continue
  678.  
  679. EXPAND40:   STOSB                ; move character to output line
  680.         CMP     AL, 0AH            ; q. line feed?
  681.         JE        EXPAND50            ; a. yes .. don't count it
  682.  
  683.         INC     CURCOL            ; bump current column nbr
  684.  
  685. EXPAND50:   LOOP    EXPAND10            ; ..loop till input exhausted
  686.  
  687.         MOV     SI, OFFSET OBUFF        ; si -> start of output buffer
  688.         MOV     CX, DI            ; di -> just past last char of output
  689.         SUB     CX, SI            ; cx = nbr of characters in output
  690.  
  691.         POP     DI                ; restore registers
  692.         POP     DX
  693.         POP     BX
  694.         POP     AX
  695.         RET                 ; ..and return to caller
  696.  
  697. EXPAND        ENDP
  698. ; ---------------------------------------------------------------------------
  699. ;   LINEPRT - Handle printing a line
  700. ;     Entry:
  701. ;    dx -> start of line
  702. ;    cx =  nbr of characters to print
  703. ;     Exit:
  704. ;    dx -> start of next line
  705. ;    cx =  0
  706. ; ---------------------------------------------------------------------------
  707. LINEPRT     PROC
  708.  
  709.         JCXZ    LINEPRT90            ; if nothing to print.. return
  710.  
  711.         CMP     NEWPAGE, 1            ; q. need a new page?
  712.         JNE     LINEPRT10            ; a. no .. continue
  713.  
  714.         CALL    PAGEBREAK            ; else .. do a pagebreak
  715.  
  716. LINEPRT10:  CALL    WRITE            ; write the line
  717.  
  718.         ADD     DX, CX            ; dx -> start of next line
  719.         XOR     CX, CX            ; cx = nbr of characters to print
  720. LINEPRT90:  RET
  721.  
  722. LINEPRT     ENDP
  723. ; ---------------------------------------------------------------------------
  724. ;   MKTITLE - Make the title line be ready to print
  725. ;     Exit:
  726. ;    dx -> title line
  727. ;    cx =  title line length
  728. ; ---------------------------------------------------------------------------
  729. MKTITLE     PROC
  730.         PUSH    AX                ; save registers
  731.         PUSH    BX
  732.         PUSH    DI
  733.  
  734.         MOV     AX, PAGENO            ; ax = page number
  735.         MOV     CX, 4            ; cx = length of output
  736.         MOV     BL, ' '                 ; bl = fill char (blank)
  737.         MOV     DI, OFFSET TITLE_PGE    ; di -> output area
  738.         CALL    ITOA            ; .. fill in page number
  739.  
  740.         MOV     DX, OFFSET TITLE_        ; dx -> title
  741.         MOV     CX, TITLE_LEN        ; cx = length of title
  742.         CALL    WRITE            ; print title line
  743.  
  744.         POP     DI                ; restore registers
  745.         POP     BX
  746.         POP     AX
  747.         RET                 ; return to caller
  748.  
  749. MKTITLE     ENDP
  750. ; ---------------------------------------------------------------------------
  751. ;   PAGEBREAK - Handle page overflow condition
  752. ; ---------------------------------------------------------------------------
  753. PAGEBREAK   PROC
  754.  
  755.             Push    AX                      ; save registers
  756.         PUSH    BX                ;
  757.         PUSH    CX                      ;
  758.         PUSH    DX                      ;
  759.  
  760.         TEST    PAGENO, 1            ; q. finishing up with left page?
  761.         JZ        PAGEBRK20            ; a. no .. do other page
  762.  
  763.         MOV     DX, OFFSET STRING3        ; dx -> get to right page string
  764.         MOV     CX, STRING3_LEN        ; cx = length
  765.         CALL    WRITE            ; write out 1st part of string
  766.  
  767.         MOV     BX, 66            ; bx = loop count
  768.         MOV     CX, 3            ; cx = nbr of chars to print
  769.         MOV     DX, OFFSET STRING4        ; dx -> vertical bar string
  770.  
  771. PAGEBRK10:  CALL    WRITE            ; write on line of vertical bars
  772.  
  773.         DEC     BX                ; q. done yet?
  774.         JNZ     PAGEBRK10            ; a. no .. keep looping
  775.  
  776.         MOV     DX, OFFSET STRING5        ; dx -> string to finish up
  777.         MOV     CX, STRING5_LEN        ; cx = length
  778.             Call    Write                   ;; Output it...
  779.         JMP     PAGEBRK30            ; ..and continue w/common code
  780.  
  781. PAGEBRK20:
  782.  
  783.             Mov     AX,CHandle              ;; Get current handle
  784.             Xchg    AX,NHandle              ;; Get next handle
  785.             Mov     CHandle,AX              ;; Swap current handle
  786.  
  787.             MOV     DX, OFFSET STRING6        ; dx -> get to left page string
  788.         MOV     CX, STRING6_LEN        ; cx = length
  789.             CALL    WRITE            ; print the init line
  790.             Mov     AL,0Ch                  ;; Get a formfeed
  791.             Mov     String6,AL              ;; Don't want FF on first pass
  792.  
  793. Pagebrk30:  MOV     LINECNT, 1            ; reset line counter
  794.         MOV     NEWPAGE, 0            ; clear new page request flag
  795.         INC     PAGENO            ; ..and bump page number
  796.  
  797.         CALL    MKTITLE            ; print title line
  798.  
  799.         POP     DX                ; restore registers
  800.         POP     CX                ;
  801.         POP     BX                ;
  802.             Pop     AX                      ;
  803.         RET                 ; ..and return to caller
  804.  
  805. PAGEBREAK   ENDP
  806. ; ---------------------------------------------------------------------------
  807. ;   BUMPLINE - Increment line counter and test for overflow
  808. ; ---------------------------------------------------------------------------
  809. BUMPLINE    PROC
  810.         INC     LINECNT            ; increment line counter
  811.  
  812.         CMP     LINECNT, 66         ; q. reached max lines/page?
  813.         JLE     BUMPLINE90            ; a. no .. continue
  814.  
  815.         MOV     NEWPAGE, 1            ; else .. show we'll need a new one
  816.  
  817. BUMPLINE90: RET                 ; ..then return to caller
  818.  
  819. BUMPLINE    ENDP
  820. ; ---------------------------------------------------------------------------
  821. ;   PROLOGUE - Put out laserjet initialization string
  822. ; ---------------------------------------------------------------------------
  823. PROLOGUE    PROC
  824.  
  825.         PUSH    CX                ; save registers
  826.         PUSH    DX
  827. ;
  828. ; The initialization string is first sent to the back side file, then to 
  829. ; the printer.  The handles are set up so the next handle to be used (NHandle)
  830. ; points to the back side file, and after the initialization string is sent
  831. ; to the printer with the second call, the current handle (CHandle) points
  832. ; to the printer.  After each physical page is printed, the two handles are
  833. ; swapped.  The Write subroutine writes to whichever file is pointed to by
  834. ; Chandle.
  835. ;
  836.             Mov     AX,BHandle              ;; Get pointer to back side file
  837.             Mov     CHandle,AX              ;; Point to back side file
  838.             Mov     NHandle,AX              ;; Also save as next handle to use
  839.         MOV     DX, OFFSET STRING1        ; dx -> initialization string
  840.         MOV     CX, STRING1_LEN        ; cx = length
  841.         CALL    WRITE            ; print the init line
  842.  
  843.             Mov     AX,PHandle              ;; Point to Printer
  844.             Mov     CHandle,AX              ;; Save as current handle
  845.             Mov     CX,String1_Len          ;; CX = Length
  846.             Mov     DX,Offset String1       ;; DX -> Initialization string
  847.             Call    Write                   ;; And send to printer
  848.  
  849.         MOV     PAGENO, 1            ; setup page number
  850.         MOV     CURCOL, 1            ; ..and current column number
  851.         MOV     LINECNT, 1            ; ..and line counter
  852.         MOV     HPSTATE, 1            ; ..show in left page
  853.         MOV     USEDLEN, 0            ; ..clear column position
  854.         CALL    MKTITLE            ; print title line
  855.  
  856.         POP     DX                ; restore registers
  857.         POP     CX                ;
  858.         RET                 ; ..and return to caller
  859.  
  860. PROLOGUE    ENDP
  861. ; ---------------------------------------------------------------------------
  862. ;   EPILOGUE - Put out laserjet finish up string
  863. ; ---------------------------------------------------------------------------
  864. EPILOGUE    PROC
  865.  
  866.             Push    AX                      ; save registers
  867.             Push    BX                      ;
  868.         PUSH    CX                ;
  869.         PUSH    DX                      ;
  870.  
  871. ;
  872. ; Calculate how many formfeeds we need at the end of the back side file.
  873. ;
  874.             Mov     AX,BHandle              ;; Point to back side file
  875.             Mov     CHandle,AX              ;; Make current output file
  876.             Mov     AX,PageNo               ;; Get last page number
  877.             Inc     AX                      ;; Add 1
  878.             Shr     AX,1                    ;; Divide by 2
  879.             Mov     BX,1                    ;; Only one formfeed needed
  880.             Test    AX,1                    ;; Is physical page odd?
  881.             Jz      Epil10                  ;; No - page is even
  882.             Inc     BX                      ;; Page is odd - 2 formfeeds
  883.  
  884. Epil10:        MOV     DX, OFFSET STRING2        ; dx -> termination string
  885.         MOV     CX, STRING2_LEN        ; cx = length
  886.         CALL    WRITE            ; print the init line
  887.             Dec     BX                      ;; Need any more?
  888.             Jnz     Epil10                  ;; Continue as needed
  889. ;
  890. ; Now send the reset string to the printer itself.
  891. ;
  892.             Mov     AX,PHandle              ;; Point to the printer
  893.             Mov     CHandle,AX              ;; Make it current
  894.             Mov     DX,Offset String2       ;; DX -> termination string
  895.             Mov     CX,String2_len          ;; CX = length
  896.             Call    Write                   ;; And send it.
  897.  
  898.             Mov     String6,0Dh             ;; Don't want FF on first pass
  899.  
  900.         MOV     HPSTATE, 0            ; show back to initialization state
  901.  
  902.         POP     DX                ; restore registers
  903.         POP     CX                ;
  904.             Pop     BX                      ;
  905.             Pop     AX                      ;
  906.  
  907.         RET                 ; ..and return to caller
  908.  
  909. EPILOGUE    ENDP
  910. ; ---------------------------------------------------------------------------
  911. ;   WRITE - Send a string to the printer
  912. ;     Entry:
  913. ;    dx -> string to write
  914. ;    cx =  nbr of characters
  915. ; ---------------------------------------------------------------------------
  916. WRITE        PROC
  917.  
  918.         PUSH    AX                ; save registers
  919.         PUSH    BX
  920.  
  921.         MOV     AH, 40H            ; ah = write to file/device function
  922.         MOV     BX, CHANDLE         ; bx = printer handle
  923.         INT     21H             ; issue dos call
  924.  
  925.         POP     BX                ; restore registers
  926.         POP     AX                ;
  927.         RET                 ; ..and return to caller
  928.  
  929. WRITE        ENDP
  930. ; ---------------------------------------------------------------------------
  931. ;   UPCASE - Convert command line arguments to uppercase
  932. ; ---------------------------------------------------------------------------
  933. UPCASE        PROC
  934.  
  935.         PUSH    SI                ; save caller regs
  936.         PUSH    DI
  937.         MOV     SI, 81H            ; si -> start of parm area
  938.         MOV     DI, SI            ; .. same for di
  939.         CLD                 ; .. assure ascending
  940.  
  941. UPCASE10:   LODSB                ; al = char
  942.         CMP     AL, 0DH            ; q. end of line?
  943.         JE        UPCASE90            ; a. yes .. end of line!
  944.         CMP     AL, 'a'                 ; q. is it below 'a'?
  945.         JB        UPCASE20            ; a. yes .. continue
  946.         CMP     AL, 'z'                 ; q. is it above 'z'?
  947.         JA        UPCASE20            ; a. yes .. continue
  948.         SUB     AL, 20H            ; set to upper case
  949.  
  950. UPCASE20:   STOSB                ; save the byte
  951.         JMP     UPCASE10            ; .. and continue
  952.  
  953. UPCASE90:   POP     DI                ; restore caller regs
  954.         POP     SI
  955.         RET                 ; .. and return to caller
  956.  
  957. UPCASE        ENDP
  958. ; ---------------------------------------------------------------------------
  959. ;   ATOI - Translate an ascii value to binary
  960. ;     Entry:
  961. ;    si -> ascii value
  962. ;     Exit:
  963. ;    al =  binary value
  964. ; ---------------------------------------------------------------------------
  965. ATOI        PROC
  966.  
  967.         XOR     AX, AX            ; ax = accumulator = 0
  968.  
  969. ATOI10:     CMP     BYTE PTR [SI], '0'      ; q. below ascii 0?
  970.         JB        ATOI90            ; a. yes.. exit
  971.  
  972.         CMP     BYTE PTR [SI], '9'      ; q. above ascii 9?
  973.         JA        ATOI90            ; a. yes.. exit
  974.  
  975.         XOR     AH, AH            ; reset ah
  976.         MOV     BL, 10            ; bl = multiply value
  977.         MUL     BL                ; .. multiply by 10
  978.         MOV     BL, [SI]            ; bl = value
  979.         AND     BL, 0FH            ; .. upper bits off
  980.         ADD     AL, BL            ; .. add to bl
  981.  
  982.         INC     SI                ; si -> next char
  983.         JMP     ATOI10            ; .. tranlate it
  984.  
  985. ATOI90:     RET                 ; .. return to caller
  986.  
  987. ATOI        ENDP
  988. ; ---------------------------------------------------------------------------
  989. ;   ITOA - Integer to ASCII characters
  990. ;     Entry:
  991. ;    ax =  value to convert
  992. ;    bl =  fill character
  993. ;    cx =  nbr of characters
  994. ;    di -> start of alpha area
  995. ; ---------------------------------------------------------------------------
  996. ITOA        PROC
  997.  
  998.         PUSH    AX                ; save registers
  999.         PUSH    BX
  1000.         PUSH    CX
  1001.         PUSH    DX
  1002.         PUSH    DI
  1003.         PUSHF
  1004.         STD                 ; ..and set direction flag
  1005.  
  1006.         ADD     DI, CX            ; di -> 1st char past work area
  1007.         DEC     DI                ; di -> last char in work area
  1008.         PUSH    BX                ; save fill character
  1009.         MOV     BX, 10            ; bx = divisor
  1010.  
  1011. ITOA10:     OR        AX, AX            ; q. any value to convert?
  1012.         JZ        ITOA20            ; a. no .. exit loop
  1013.  
  1014.         XOR     DX, DX            ; dx:ax = value to divide
  1015.         IDIV    BX                ; ax = dividend, dx = remainder
  1016.         OR        DL, 30H            ; dl = ASCII number
  1017.         MOV     [DI], DL            ; store character in buffer
  1018.         DEC     DI                ; di -> next output char location
  1019.  
  1020.         DEC     CX                ; q. any more room in buffer?
  1021.         JNZ     ITOA10            ; a. yes .. continue loop
  1022.  
  1023.         POP     BX                ; restore register
  1024.         JMP     ITOA90            ; ..and exit through common code
  1025.  
  1026. ITOA20:     POP     AX                ; al = fill character
  1027.  
  1028. ITOA30:     STOSB                ; store fill character
  1029.  
  1030.         DEC     CX                ; q. any more room in buffer?
  1031.         JNZ     ITOA30            ; a. yes .. continue loop
  1032.  
  1033. ITOA90:     POPF                ; restore flags
  1034.         POP     DI                ; ..and registers
  1035.         POP     DX                ;
  1036.         POP     CX                ;
  1037.         POP     BX                ;
  1038.         POP     AX                ;
  1039.         RET                 ; ..and return
  1040.  
  1041. ITOA        ENDP
  1042. ; ---------------------------------------------------------------------------
  1043. ;   Uninitialized data areas
  1044. ; ---------------------------------------------------------------------------
  1045. UDATA        EQU     $                ; start of unitialized data
  1046. PAGENO        EQU     WORD PTR UDATA        ; current page number
  1047. CURCOL        EQU     WORD PTR PAGENO+2        ; current column
  1048. LINECNT     EQU     WORD PTR CURCOL+2        ; line count
  1049. EDRV        EQU     BYTE PTR LINECNT+2        ; current disk
  1050. EDIR        EQU     BYTE PTR EDRV+1        ; current directory
  1051. FILENAME    EQU     BYTE PTR EDIR+65        ; filename specifed as ARG1
  1052. LASTBUFF    EQU     BYTE PTR FILENAME+13    ; last buffer indicator
  1053. FHANDLE     EQU     WORD PTR LASTBUFF+1     ; input file handle
  1054. BUFFER        EQU     BYTE PTR FHANDLE+2        ; file buffer
  1055. BUFLEN        EQU     2048            ; length of buffer
  1056. USEDLEN     EQU     BYTE PTR BUFFER+BUFLEN  ; used length in a logical line
  1057. OBUFF        EQU     BYTE PTR USEDLEN+1        ; output buffer - must be last!
  1058.  
  1059. CSEG        ENDS                ; end of code segment
  1060.         END     START
  1061.